import hashlib
import logging
import math
import os
import random
import time
from decimal import Decimal, ROUND_FLOOR
from pathlib import Path

from django.http import JsonResponse


def MD5(val):
    md5 = hashlib.md5()
    md5.update(val.encode(encoding='utf-8'))
    return md5.hexdigest()

def is_empty_str(val):
    if type(val) is not str:
        return True
    return val == ''


def str_len(val):
    typ = type(val)
    if typ != str:
        if typ == int or type == float:
            val = str(val)
        else:
            return 0
    return len(val)


def rand_str(length, typ=0):
    lower = 'abcdefghijklmnopqrstuvwxtz'
    upper = 'ABCDEFGHIJKLMNOPQRSTUVWXTZ'
    numbers = '0123456789'
    safe = '2346789ABCDEFGHJKLMNPRTUVWXTZ'
    charset = lower + upper + numbers
    if typ == 1:
        charset = lower + numbers
    elif typ == 2:
        charset = upper + numbers
    elif typ == 3:
        charset = safe
    elif typ == 4:
        charset = numbers
    return ''.join(random.sample(charset, length))


def get_ip(request):
    if 'HTTP_X_FORWARDED_FOR' in request.META:
        ip = request.META['HTTP_X_FORWARDED_FOR']
    else:
        ip = request.META['REMOTE_ADDR']
    return ip


def success(data=None, **kwargs):
    resp = {
        'errcode': 0,
    }
    if data is not None:
        resp['data'] = data
    return JsonResponse({
        **resp,
        **kwargs
    })


def error(message='', status=200, **kwargs):
    resp = {
        "errcode": 10000,
        **kwargs
    }
    if message != '':
        resp['message'] = message
    return JsonResponse(resp, status=status)


def get_ts():
    return int(time.time())


def str_to_dec(num_str):
    num_dec = Decimal('0')
    try:
        num_dec = Decimal(num_str)
    except Exception:
        pass
    return num_dec


def to_int(val):
    num_int = 0
    try:
        num_int = int(val)
    except Exception:
        pass
    return num_int


def fen_to_yuan(fen):
    return (Decimal(str(fen)) * Decimal('0.01')).quantize(Decimal('0.00'))


def to_dec(val):
    dec_val = Decimal('0')
    try:
        val_typ = type(val)
        if val_typ is Decimal:
            return val
        else:
            dec_val = Decimal(str(val))
    except Exception:
        pass
    return dec_val


def mkdir_if_not_exist(path):
    ph = Path(path)
    if not ph.exists():
        try:
            os.makedirs(ph)
        except Exception as e:
            print(e)


def calc_half_price(num, price,is_half):
    pns = 1
    if num < 0:
        pns = -1
    num = abs(num)
    int_val = int(num)
    dec_part_val = to_dec(num) - to_dec(int_val)
    is_odd = int_val % 2 == 0
    half_num = math.floor(int_val / 2)
    dec_price = to_dec(price)
    if is_half == 1:
        half_number = to_dec(1.5)
    else:
        half_number = to_dec(1)
    dec_total_price = to_dec(half_num) * dec_price * half_number + dec_part_val * dec_price
    if not is_odd:
        dec_total_price += dec_price
    return dec_total_price.quantize(Decimal('0.00')) * pns

def calc_half_refund_amount(num, return_num, subtotal,is_half):
    num_dec = to_dec(num)
    return_num_dec = to_dec(return_num)
    if num_dec == return_num_dec:
        return subtotal,Decimal('0')
    subtotal_dec = to_dec(subtotal)
    int_val = int(num)
    dec_part_val = num_dec - to_dec(int_val)
    is_odd = int_val % 2 == 0
    half_num = math.floor(int_val / 2)
    half_num_dec = to_dec(half_num)
    if is_odd:
        if is_half == 1:
            dec_price = subtotal_dec / (to_dec(1.5) * half_num_dec + dec_part_val)
        else:
            dec_price = subtotal_dec / (to_dec(1) * half_num_dec + dec_part_val)
    else:
        if is_half == 1:
            dec_price = subtotal_dec / (to_dec(1.5) * half_num_dec + dec_part_val + 1)
        else:
            dec_price = subtotal_dec / (to_dec(1) * half_num_dec + dec_part_val + 1)
    dec_price = dec_price.quantize(Decimal('0.00'), ROUND_FLOOR)
    if is_half == 1:
        dec_number = to_dec(0.5)
    else:
        dec_number = to_dec(0)
    if return_num_dec <= half_num_dec:
        refund_amount_dec = return_num_dec * dec_price * dec_number
        half_num_dec = return_num_dec
    else:
        refund_amount_dec = (return_num_dec - half_num_dec) * dec_price + half_num_dec * dec_price * dec_number
    return refund_amount_dec.quantize(Decimal('0.00')), half_num_dec

def logger(*msg, symbol='*', symbol_width=5, start_flag=' ', end_flag=' ', level='debug', log_name='my-log'):
    level_name_upper = level.upper()
    valid_level_code_arr = [0, 10, 20, 30, 40, 50]
    valid_level_name_arr = ['NOTSET', 'DEBUG', 'INFO', 'WARN', 'ERROR', 'CRITICAL']
    level_code = 1
    if level_name_upper in valid_level_name_arr:
        i = valid_level_name_arr.index(level_name_upper)
        level_code = valid_level_code_arr[i]
    log = logging.getLogger(log_name)
    fix_str = symbol.ljust(symbol_width, symbol)
    log.log(level_code, '{}{}{}{}{}'.format(fix_str, start_flag, msg, end_flag, fix_str))
